#include "mainwindow.h"
#include <QtGui>
#include "RulesDialog.h"
#include <QTextCursor>
#include "Completer.h"
#include "common.h"
#include "CompletionsDialog.h"
#include "Parser.h"
#include "AboutDialog.h"
#include <QScriptEngineDebugger>
#include <QScriptEngine>
//#include <QScriptDebuggerLocalsModel>

//-------------------------------------

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    completer( 0 ),
    parser( 0 ),
    mdl( 0 )
{
    resize( 1200, 700 );

    deployMenu();

    QFont font;
    font.setFamily( DEFAULT_FONT_FAMILY );
    font.setFixedPitch( true );
    font.setPointSize( DEFAULT_FONT_SIZE );

    parser = new Parser( this );
    completer = new Completer( this );

    editor = new TextEditor;
    editor->setFont( font );
    editor->setCompleter( completer );
    setCentralWidget( editor );

    highlighter = new Highlighter( editor->document() );
    if( QFile::exists( RULES_FILE_NAME ) )
        highlighter->load( RULES_FILE_NAME );
    else
        highlighter->save( RULES_FILE_NAME );

    makeWordsTree();
    mdl = dynamic_cast< QStandardItemModel* >( getModel( KEYS_TREE_FILE_NAME ) );

    if( mdl )
    {
        parser->acceptModel( mdl );
        completer->setModel( mdl );
    }

    connect( parser, SIGNAL( sgnHighlightToken(QString) ), highlighter, SLOT( sltAddRule(QString) ) );
    connect( editor, SIGNAL( sgnParse(QString) ), parser, SLOT( sltParse(QString) ) );
    connect( editor, SIGNAL( sgnReloadModel() ), this, SLOT( sltReloadModel() ) );
}

//-------------------------------------

MainWindow::~MainWindow()
{
}

//-------------------------------------

void MainWindow::deployMenu()
{
    QMenu * fileMenu = new QMenu( "File", this );
    menuBar()->addMenu( fileMenu );
    fileMenu->addAction( "New", this, SLOT( sltNewFile() ) );
    fileMenu->addAction( "Open...", this, SLOT( sltOpenFile() ) );
    fileMenu->addAction( "Save as...", this, SLOT( sltSaveAsFile() ) );
    fileMenu->addAction( "Exit", qApp, SLOT( quit() ) );

    QMenu * settingsMenu = new QMenu( "Settings", this );
    menuBar()->addMenu( settingsMenu );
    settingsMenu->addAction( "Backgroung Color", this, SLOT( sltSetBackgroundColor() ) );
    settingsMenu->addAction( "Font Color", this, SLOT( sltSetFontColor() ) );
    QAction * ww = settingsMenu->addAction( "Word Wrap", this, SLOT( sltSetWordWrap() ) );
    ww->setCheckable( true );
    ww->setChecked( editor->WordWrap() );

    QMenu * tokensMenu = new QMenu( "Tokens", this );
    menuBar()->addMenu( tokensMenu );
    tokensMenu->addAction( "Manage Rules", this, SLOT( sltManageRules() ) );
    tokensMenu->addAction( "Manage Tokens", this, SLOT( sltManageCompletes() ) );
    tokensMenu->addAction( "Show all tokens tree", this, SLOT( sltShowAllTokens() ) );

    QMenu * helpMenu = new QMenu( "Help", this );
    menuBar()->addMenu( helpMenu );
    helpMenu->addAction( "About", this, SLOT( sltAbout() ) );

}

//-------------------------------------

void MainWindow::sltNewFile()
{
    editor->clear();
}

//-------------------------------------

void MainWindow::sltOpenFile( const QString & f )
{
    QString fileName = f;

    if( fileName.isNull() )
        fileName = QFileDialog::getOpenFileName( this, "Open File", "", "Internal Script Files ( *.js )" );

    if( !fileName.isEmpty() )
    {
        QFile file( fileName );
        if( file.open( QFile::ReadOnly | QFile::Text ) )
        {
            loadModel();
            editor->setPlainText( file.readAll() );
            file.close();
            editor->parseText();

            runDebugger( fileName );
        }
    }
}

//-------------------------------------

void MainWindow::sltSaveAsFile()
{
    QString f = QFileDialog::getSaveFileName( this, "Save as ...", "", "Internal Script Files ( *.* )");
    if( !f.isEmpty() )
    {
        QFile ff( f );
        if( ff.open( QFile::WriteOnly | QFile::Text ) )
        {
            ff.write( editor->toPlainText().toAscii() );
            ff.close();
        }
    }
}

//-------------------------------------

void MainWindow::sltManageRules()
{
    RulesDialog * dlg = new RulesDialog();
    dlg->setupHighlighter( highlighter );
    if( dlg->exec() == QDialog::Accepted )
    {
        highlighter->save( RULES_FILE_NAME );
        editor->updateHighlighting();
    }
    delete dlg;
}

//-------------------------------------

void MainWindow::sltManageCompletes()
{
    CompletionsDialog * dlg = new CompletionsDialog;
    if( dlg->exec() == QDialog::Accepted )
    {
        sltReloadModel();
        parser->sltParse( editor->toPlainText() );
    }
    delete dlg;
}

//-------------------------------------

QAbstractItemModel * MainWindow::getModel( const QString & file, QStandardItemModel * model )
{
    QFile f( file );
    if( !f.open( QFile::ReadOnly ) )
        return new QStringListModel( completer );

    QStandardItemModel * m;
    if( model )
        m = model;
    else
        m = new QStandardItemModel( completer );
    QVector< QStandardItem* > parents(10);
    parents[0] = m->invisibleRootItem();

    while( !f.atEnd() )
    {
        QString line = f.readLine();
        QString trimmedLine = line.trimmed();
        if( line.isEmpty() || trimmedLine.isEmpty() )
            continue;

        QRegExp re( "^\\s+" );
        int nonws = re.indexIn( line );
        int i = 0;
        if( nonws == -1 )
        {
            i = 0;
        }
        else
        {
            if( line.startsWith( "\t" ) )
            {
                i = re.cap(0).length();
            }
            else
            {
                i = re.cap(0).length()/4;
            }
        }

        if( i+1 >= parents.size() )
            parents.resize( parents.size()*2 );

        QStandardItem * item = new QStandardItem;
        item->setText( trimmedLine );
        parents[ i ]->appendRow( item );
        parents[ i+1 ] = item;
    }


    return m;
}

//-------------------------------------

void MainWindow::sltShowAllTokens()
{
    QTreeView * completesTreeView = new QTreeView;
    completesTreeView->setModel( mdl );
    completesTreeView->header()->hide();
    completesTreeView->expandAll();
    completesTreeView->setGeometry( 20, 40, 300, 600 );
    completesTreeView->show();
}

//-------------------------------------

void MainWindow::sltReloadModel()
{
    if( mdl )
    {
        loadModel();
    }
}

//-------------------------------------

void MainWindow::loadModel()
{
    mdl->clear();
    getModel( KEYS_TREE_FILE_NAME, mdl );
}

//-------------------------------------

void MainWindow::sltAbout()
{
    AboutDialog * dlg = new AboutDialog;
    dlg->exec();
}

//-------------------------------------

void MainWindow::sltSetBackgroundColor()
{
    QColor c = QColorDialog::getColor( editor->getBackgroundColor() );
    if( c.isValid() )
    {
        editor->setBackgroungColor( c );
    }
}

//-------------------------------------

void MainWindow::sltSetFontColor()
{
    QColor c = QColorDialog::getColor( editor->getFontColor() );
    if( c.isValid() )
    {
        editor->setFontColor( c );
    }
}

//-------------------------------------

void MainWindow::sltSetWordWrap()
{
    editor->setWordWrap( !editor->WordWrap() );
}

//-------------------------------------

void MainWindow::runDebugger( QString & fileName )
{
    QScriptEngine engine;
    QScriptEngineDebugger sedbg;
    sedbg.attachTo( &engine );

    QString code = editor->toPlainText();
    engine.evaluate( code, fileName );


    //QScriptDebuggerLocalsModel * m = sedbg.localsModel();

    //sedbg.setAutoShowStandardWindow( true );

    //sedbg.standardWindow()->show();
}














